package com.echo.register.service;

import com.alibaba.fastjson.JSON;
import com.echo.register.commons.Constants;
import com.echo.register.commons.proto.VoteReq;
import com.echo.register.commons.proto.VoteResp;
import com.echo.register.commons.rabbitMQ.DetailMessage;
import com.echo.register.commons.rabbitMQ.MQSender;
import com.echo.register.commons.rabbitMQ.RecordsMessage;
import com.echo.register.commons.rabbitMQ.VoteMessage;
import com.echo.register.commons.redis.CadidateKey;
import com.echo.register.commons.redis.DetailInfoKey;
import com.echo.register.commons.redis.RecordsKey;
import com.echo.register.commons.redis.RedisClient;
import com.echo.register.commons.result.RetCode;
import com.echo.register.commons.utils.CSVUtils;
import com.echo.register.commons.utils.CommonUtils;
import com.echo.register.commons.utils.ObjectUtils;
import com.echo.register.commons.utils.UUIDGenerator;
import com.echo.register.domain.VoteCadidate;
import com.echo.register.domain.VoteDetailInfo;
import com.echo.register.domain.VoteRecords;
import com.echo.register.mapper.CadidateMapper;
import com.echo.register.mapper.DetailInfoMapper;
import com.echo.register.mapper.RecordsMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

@Service
public class VoteSerivce {

    private static Logger logger = LoggerFactory.getLogger(VoteSerivce.class);

    @Resource
    RecordsMapper recordsMapper;
    @Resource
    CadidateMapper cadidateMapper;
    @Resource
    DetailInfoMapper detailInfoMapper;
    @Resource
    RedisClient redisClient;
    @Resource
    MQSender mqSender;

    public static String COOKIE_UM_TOKEN = "um_token";

    public synchronized VoteResp vote(HttpServletRequest request, VoteReq voteReq) {

        VoteResp voteResp = new VoteResp();
//        Cookie cookie = CookieHolder.get();
//        if (cookie == null) {
//            voteResp.setMsg(RetCode.GetMsg(RetCode.FAIL_COOKIE));
//            voteResp.setFlag(RetCode.FAIL_COOKIE);
//            logger.error("Not get the cookie");
//            return voteResp;
//        }
//
//        logger.info("cookie's value is {}", cookie.getValue());
//        String umId = cookie.getValue().split(Constants.COOKIE_SPLIT)[0];
        String ip = CommonUtils.getIpAddress(request);
        if(ip == null || ip.equals(Constants.EMPTY)){
            voteResp.setFlag(RetCode.FAIL);
            voteResp.setMsg("IP地址为空");
            return voteResp;
        }

        HttpSession session = request.getSession();
        VoteRecords voteRecords = (VoteRecords)session.getAttribute("records");
        if(!ObjectUtils.isNotNullOrEmpty(voteRecords)) {

            voteRecords = getRecordsByIp(ip);
            if (voteRecords == null) {
                voteResp.setMsg("没有当前um号登录信息");
                voteResp.setFlag(RetCode.FAIL_COOKIE);
                logger.info("There is no records by umId: {}", ip);
                return voteResp;
            }
        }

        VoteCadidate cadidate = getCadidateInfo(voteReq.getCadidateId());
        if (!cadidate.getCadidateFlag()) {
            voteResp.setFlag(RetCode.FAIL);
            voteResp.setMsg("候选人已失效");
            logger.info("Cadidate was valid!");
            return voteResp;
        }

        //检查该um是否已经投过该候选人
        if(checkVoteChance(voteRecords.getUmId(), voteReq.getCadidateId())){
            voteResp.setFlag(RetCode.FAIL);
            voteResp.setMsg("今天已经赞过一次啦～");
            logger.info("Already vote!");
            return voteResp;
        }
        //候选人票数累加
        add(cadidate);
        //投票人记录处理
        recordsHandle(voteRecords, voteReq.getCadidateGroup(), voteReq.getCadidateId());

        //加入消息队列进行数据库同步
        VoteMessage voteMessage = new VoteMessage();
        voteMessage.setCadiateId(cadidate.getCadidateId());
        voteMessage.setCadidate(cadidate);
        mqSender.sendVoteMessage(voteMessage);

        voteResp.setFlag(RetCode.SUCCESS);
        voteResp.setCadidateVotes(cadidate.getCadidateTotal());
        return voteResp;
    }

    public boolean exportCVS() {
        try {
            List<VoteDetailInfo> detailInfos = detailInfoMapper.getDetailList();
            String[] fileds = new String[]{"detailId", "umId", "cadidateId", "createdTime"};
            LinkedHashMap map = new LinkedHashMap();
            map.put("1", "序号");
            map.put("2", "投票人um");
            map.put("3", "候选人um");
            map.put("4", "投票时间");
            String outputPath = "D:/";
            CSVUtils.createCSVFile(detailInfos, map, outputPath, "投票明细");
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    private VoteRecords getRecordsByUmId(String umId) {
        //先从缓存中获取
        VoteRecords records = redisClient.getObject(VoteRecords.class, umId);
        logger.info("Get from redis, records: {}", JSON.toJSON(records));
        //判断对象是否为空
        if (!ObjectUtils.isNotNullOrEmpty(records)) {
            records = recordsMapper.getRecordsByUmId(umId);
            logger.info("Get from database, records: {}", JSON.toJSON(records));
        }
        return records;
    }

    private VoteRecords getRecordsByIp(String ip) {
        //先从缓存中获取
        VoteRecords records = redisClient.getObject(VoteRecords.class, ip);
        logger.info("Get from redis, records: {}", JSON.toJSON(records));
        //判断对象是否为空
        if (!ObjectUtils.isNotNullOrEmpty(records)) {
            records = recordsMapper.getRecordsByIp(ip);
            logger.info("Get from database, records: {}", JSON.toJSON(records));
        }
        return records;
    }

    private void updateRecords(VoteRecords records) {
        redisClient.setexObjec(records.getUmId(), records, RecordsKey.TOKEN_EXPIRE);
        //压入消息队列中等待处理
        RecordsMessage recordsMessage = new RecordsMessage();
        recordsMessage.setVoteRecords(records);
        mqSender.sendRecordsMessage(recordsMessage);
    }

    private VoteCadidate getCadidateInfo(String cadidateId) {
        logger.info("Cadidate id is {}", cadidateId);
        //先从缓存中获取
        VoteCadidate cadidate = redisClient.getObject(VoteCadidate.class, cadidateId);
        logger.info("Get from redis, caidate is : {}", JSON.toJSON(cadidate));
        //判断对象是否为空
        if (!ObjectUtils.isNotNullOrEmpty(cadidate)) {
            cadidate = cadidateMapper.getCadidateById(cadidateId);
            logger.info("Get from database, cadiate is {}", JSON.toJSON(cadidate));
        }
        return cadidate;
    }

    private void add(VoteCadidate cadidate) {
        cadidate.setCadidateTotal(cadidate.getCadidateTotal() + 1);
        //先更新到缓存中
        redisClient.setexObjec(cadidate.getCadidateId(), cadidate, CadidateKey.TOKEN_EXPIRE);
    }

    private VoteRecords recordsHandle(VoteRecords voteRecords, String group, String cadidateId){
        if(group.equals(Constants.CadidateGroup.AQWS)){
            voteRecords.setRecordsAqws(voteRecords.getRecordsAqws() + 1);
        }else if(group.equals(Constants.CadidateGroup.FWMY)){
            voteRecords.setRecordsFwmy(voteRecords.getRecordsFwmy() + 1);
        }else if(group.equals(Constants.CadidateGroup.KJCX)){
            voteRecords.setRecordsKjcx(voteRecords.getRecordsKjcx() + 1);
        }else if(group.equals(Constants.CadidateGroup.KJXR)){
            voteRecords.setRecordsKjxr(voteRecords.getRecordsKjxr() + 1);
        }else if (group.equals(Constants.CadidateGroup.SJXF)){
            voteRecords.setRecordsSjxf(voteRecords.getRecordsSjxf() + 1);
        }else {
            voteRecords.setRecordsZyyy(voteRecords.getRecordsZyyy() + 1);
        }
        //投票人处理
        voteRecords.setVoteCount(voteRecords.getVoteCount() + 1);
        voteRecords.setUpdatedTime(new Date());
        updateRecords(voteRecords);

        //插入投票记录
        String strNow = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        DetailMessage detailMessage = new DetailMessage();
        VoteDetailInfo detailInfo = new VoteDetailInfo();
        detailInfo.setDetailId(UUIDGenerator.getUUID());
        detailInfo.setCadidateId(cadidateId);
        detailInfo.setCreatedTime(strNow);
        detailInfo.setUmId(voteRecords.getUmId());
        detailMessage.setVoteDetailInfo(detailInfo);

        redisClient.setexObjec(voteRecords.getUmId()+cadidateId, strNow, DetailInfoKey.TOKEN_EXPIRE);
        mqSender.sendDetailMessage(detailMessage);

        return voteRecords;
    }

    private boolean checkVoteChance(String umId, String cadidateId){
        //先查找缓存是否有记录
        String strDate = redisClient.getObject(String.class, umId + cadidateId);
        String strNow = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        if(strDate != null && strDate.equals(strNow)){
            return true;
        }else if(ObjectUtils.isNotNullOrEmpty(detailInfoMapper.getDetailInfoByUmIdCadidateIdDate(cadidateId, umId, strNow))){
            return true;
        }
        return false;
    }
}
